Allow specifying what to build as part of `cargo build`
authorAlex Crichton <alex@alexcrichton.com>
Tue, 23 Sep 2014 16:16:25 +0000 (09:16 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 29 Sep 2014 23:54:24 +0000 (16:54 -0700)
This allows selectively building one dependency within a dependency graph for
debugging its build or such.

Closes #537

src/bin/bench.rs
src/bin/build.rs
src/bin/doc.rs
src/bin/run.rs
src/bin/test.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_compile_path_deps.rs

index 5448adfafac7d7e597abc50067efd90a98b5478c..9f9396cdb21935aca65957515336f5512ad37079 100644 (file)
@@ -42,6 +42,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             dev_deps: true,
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
+            spec: None,
         },
     };
 
index 1a977920a373fd0d833662797a9e370ac6b273cd..77047359ca6b94550e23acf30158dee7c92f3511 100644 (file)
@@ -11,7 +11,7 @@ docopt!(Options, "
 Compile a local package and all of its dependencies
 
 Usage:
-    cargo build [options]
+    cargo build [options] [<spec>]
 
 Options:
     -h, --help              Print this message
@@ -22,8 +22,15 @@ Options:
     --target TRIPLE         Build for the target triple
     --manifest-path PATH    Path to the manifest to compile
     -v, --verbose           Use verbose output
+
+If <spec> is given, then only the package specified will be build (along with
+all its dependencies). If <spec> is not given, then the current package will be
+built.
+
+For more information about the format of <spec>, see `cargo help pkgid`.
 ",  flag_jobs: Option<uint>, flag_target: Option<String>,
-    flag_manifest_path: Option<String>, flag_features: Vec<String>)
+    flag_manifest_path: Option<String>, flag_features: Vec<String>,
+    arg_spec: Option<String>)
 
 pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
     debug!("executing; cmd=cargo-build; args={}", os::args());
@@ -45,6 +52,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
         dev_deps: false,
         features: options.flag_features.as_slice(),
         no_default_features: options.flag_no_default_features,
+        spec: options.arg_spec.as_ref().map(|s| s.as_slice()),
     };
 
     ops::compile(&root, &mut opts).map(|_| None).map_err(|err| {
index a1c0beaf23670833cb26f3d08a36ef0ecdf687da..d0635359844e35a0800ccf24ae8028fa662d5c6d 100644 (file)
@@ -41,6 +41,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             dev_deps: false,
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
+            spec: None,
         },
     };
 
index afd3a27b0096d90af6e7be70b571cd39d9dbea23..f52a1e5aa2e0c4da4d03b627b9f3a50715473019 100644 (file)
@@ -38,6 +38,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
         dev_deps: true,
         features: options.flag_features.as_slice(),
         no_default_features: options.flag_no_default_features,
+        spec: None,
     };
 
     let err = try!(ops::run(&root, &mut compile_opts,
index 9f6d747382a6dc5cc9b51b1e1dc210a4b2317aff..cfecce9cdfc035a63769405d41a8701b7fffd244 100644 (file)
@@ -41,6 +41,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             dev_deps: true,
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
+            spec: None,
         },
     };
 
index 6962f5fd97e6bda222f3952c317817fe5343b50d..cfd82c0284aaf59ba19bc93207e736a1dd99e879 100644 (file)
@@ -41,12 +41,13 @@ pub struct CompileOptions<'a> {
     pub dev_deps: bool,
     pub features: &'a [String],
     pub no_default_features: bool,
+    pub spec: Option<&'a str>,
 }
 
 pub fn compile(manifest_path: &Path,
                options: &mut CompileOptions)
                -> CargoResult<ops::Compilation> {
-    let CompileOptions { env, ref mut shell, jobs, target,
+    let CompileOptions { env, ref mut shell, jobs, target, spec,
                          dev_deps, features, no_default_features } = *options;
     let target = target.map(|s| s.to_string());
     let features = features.iter().flat_map(|s| {
@@ -102,7 +103,15 @@ pub fn compile(manifest_path: &Path,
 
     debug!("packages={}", packages);
 
-    let targets = package.get_targets().iter().filter(|target| {
+    let to_build = match spec {
+        Some(spec) => {
+            let pkgid = try!(resolve_with_overrides.query(spec));
+            packages.iter().find(|p| p.get_package_id() == pkgid).unwrap()
+        }
+        None => &package,
+    };
+
+    let targets = to_build.get_targets().iter().filter(|target| {
         match env {
             // doc-all == document everything, so look for doc targets
             "doc" | "doc-all" => target.get_profile().get_env() == "doc",
@@ -115,7 +124,7 @@ pub fn compile(manifest_path: &Path,
         let mut config = try!(Config::new(*shell, jobs, target));
         try!(scrape_target_config(&mut config, &user_configs));
 
-        try!(ops::compile_targets(env.as_slice(), targets.as_slice(), &package,
+        try!(ops::compile_targets(env.as_slice(), targets.as_slice(), to_build,
                                   &PackageSet::new(packages.as_slice()),
                                   &resolve_with_overrides, &sources,
                                   &mut config))
index 307743177f1df9cee31167abd4eb0fa53b73cf56..dd00134cfd30aadc7208c93f6bf40dfacc9b6c4f 100644 (file)
@@ -60,9 +60,10 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package,
     debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);
 
     let dest = uniq_target_dest(targets);
-    let host_layout = Layout::new(pkg, None, dest);
+    let root = deps.iter().find(|p| p.get_package_id() == resolve.root()).unwrap();
+    let host_layout = Layout::new(root, None, dest);
     let target_layout = config.target().map(|target| {
-        layout::Layout::new(pkg, Some(target), dest)
+        layout::Layout::new(root, Some(target), dest)
     });
 
     let mut cx = try!(Context::new(env, resolve, sources, deps, config,
@@ -76,8 +77,13 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package,
     // particular package. No actual work is executed as part of this, that's
     // all done later as part of the `execute` function which will run
     // everything in order with proper parallelism.
+    let mut dep_pkgids = HashSet::new();
+    each_dep(pkg, &cx, |dep| {
+        dep_pkgids.insert(dep.get_package_id().clone());
+    });
     for dep in deps.iter() {
         if dep == pkg { continue }
+        if !dep_pkgids.contains(dep.get_package_id()) { continue }
 
         // Only compile lib targets for dependencies
         let targets = dep.get_targets().iter().filter(|target| {
@@ -91,7 +97,9 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package,
         try!(compile(targets.as_slice(), dep, &mut cx, &mut queue));
     }
 
-    cx.primary();
+    if pkg.get_package_id() == resolve.root() {
+        cx.primary();
+    }
     try!(compile(targets, pkg, &mut cx, &mut queue));
 
     // Now that we've figured out everything that we're going to do, do it!
index d784341ca3356cf45062a7cd5afc44c815ad415e..1edd24c69f576365ac8ed574c82af79df46992cd 100644 (file)
@@ -83,6 +83,20 @@ test!(cargo_compile_with_nested_deps_shorthand {
     assert_that(
       cargo::util::process(p.bin("foo")),
       execs().with_stdout("test passed\n"));
+
+    println!("cleaning");
+    assert_that(p.process(cargo_dir().join("cargo")).arg("clean"),
+                execs().with_stdout(""));
+    println!("building baz");
+    assert_that(p.process(cargo_dir().join("cargo")).arg("build").arg("baz"),
+                execs().with_stdout(format!("{} baz v0.5.0 ({})\n",
+                                            COMPILING, p.url())));
+    println!("building foo");
+    assert_that(p.process(cargo_dir().join("cargo")).arg("build").arg("foo"),
+                execs().with_stdout(format!("{} bar v0.5.0 ({})\n\
+                                             {} foo v0.5.0 ({})\n",
+                                            COMPILING, p.url(),
+                                            COMPILING, p.url())));
 })
 
 test!(cargo_compile_with_root_dev_deps {